﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.ServiceProcess;
using System.Text;
using System.Timers;
using EBA.Framework;
using System.Security.Principal;

namespace EBA.WindowsServices
{
    /// <summary>
    /// <see cref="IWindowsService"/>托管服务控制器
    /// </summary>
    public class WindowsServiceHostingController
    {
        ServiceController _ServiceController = new ServiceController("EBA.WindowsServices", System.Environment.MachineName);
        WindowsServiceHosting _WindowsServiceHosting;

        string Id { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public WindowsServiceHostingController()
        {
            this.Id = Guid.NewGuid().ToString("N");

            this._ServiceMonitor = new Timer();
            this._ServiceMonitor.Interval = 1000 * 2; //5s
            this._ServiceMonitor.Elapsed += ServiceMonitor_Elapsed;
            this._ServiceMonitor.Enabled = true;

            this.TryConnect();

        }

        /// <summary>
        /// 连接托管服务控制服务
        /// </summary>
        public bool TryConnect()
        {
            try
            {
                if (this._WindowsServiceHosting == null)
                {
                    this._WindowsServiceHosting = GetRemotingWindowServiceHosting();

                    this._WindowsServiceHosting.BundleStarting += RemotingBundleEvenHandler.CreateDelegate(OnBundleStarting);
                    this._WindowsServiceHosting.BundleStartted += RemotingBundleEvenHandler.CreateDelegate(OnBundleStartted);
                    this._WindowsServiceHosting.BundleStopping += RemotingBundleEvenHandler.CreateDelegate(OnBundleStopping);
                    this._WindowsServiceHosting.BundleStopped += RemotingBundleEvenHandler.CreateDelegate(OnBundleStopped);
                }

                return true;
            }
            catch (RemotingException)
            {
                this._WindowsServiceHosting = null;
                this.OnWindowsServiceHostingStopped();
                return false;
            }
        }

        /// <summary>
        /// 断开与托管服务控制服务的链接
        /// </summary>
        public void TryDisconnect()
        {
            if (this._WindowsServiceHosting != null)
            {
                this._WindowsServiceHosting = null;
            }
        }

        #region BundleEventHanlder

        void OnBundleStopped(object sender, Framework.IBundleContext context)
        {
            this.OnWindowsServiceStopped(context.Bundle.Id, context.Bundle.Name);
        }

        void OnBundleStopping(object sender, Framework.IBundleContext context)
        {
            this.OnWindowsServiceStoping(context.Bundle.Id, context.Bundle.Name);
        }

        void OnBundleStartted(object sender, Framework.IBundleContext context)
        {
            this.OnWindowsServiceRunning(context.Bundle.Id, context.Bundle.Name);
        }

        void OnBundleStarting(object sender, Framework.IBundleContext context)
        {
            this.OnWindowsServiceStarting(context.Bundle.Id, context.Bundle.Name);
        }
        #endregion

        #region 托管服务启动/停止
        ServiceControllerStatus GetServiceStatus()
        {
            this._ServiceController.Refresh();
            return this._ServiceController.Status;
        }

        /// <summary>
        /// 启动托管服务
        /// </summary>
        public void StartHosting()
        {
            var status = this.GetServiceStatus();

            if (status != ServiceControllerStatus.Running && status != ServiceControllerStatus.StartPending)
            {
                this._ServiceController.Start();
            }
        }

        /// <summary>
        /// 停止托管服务
        /// </summary>
        public void StopHosting()
        {
            var status = this.GetServiceStatus();

            if (status != ServiceControllerStatus.Stopped && status != ServiceControllerStatus.StopPending)
            {
                this._ServiceController.Stop();
            }
        }
        #endregion

        #region WindowsServiceHostingEventHandlers

        #region 状态监视器
        Timer _ServiceMonitor;
        ServiceControllerStatus _LastServiceStatus;
        void ServiceMonitor_Elapsed(object sender, ElapsedEventArgs e)
        {
            var currentStatus = this.GetServiceStatus();
            if (currentStatus != this._LastServiceStatus)
            {
                switch (currentStatus)
                {
                    case ServiceControllerStatus.StartPending:
                        this.OnWindowsServiceHostingStarting();
                        break;
                    case ServiceControllerStatus.Running:
                        this.OnWindowsServiceHostingRunning();
                        break;
                    case ServiceControllerStatus.StopPending:
                        this.OnWindowsServiceHostingStoping();
                        break;
                    case ServiceControllerStatus.Stopped:
                        this.OnWindowsServiceHostingStopped();
                        break;
                    default:
                        break;
                }
                this._LastServiceStatus = currentStatus;
            }
        }
        #endregion

        #region 启动中
        void OnWindowsServiceHostingStarting()
        {
            if (this.WindowsServiceHostingStarting != null)
            {
                this.WindowsServiceHostingStarting();
            }
        }

        /// <summary>
        /// 托管服务正在启动
        /// </summary>
        public event WindowsServiceHostingEventHandler WindowsServiceHostingStarting;
        #endregion

        #region 运行中
        void OnWindowsServiceHostingRunning()
        {
            if (this.WindowsServiceHostingRunning != null)
            {
                this.WindowsServiceHostingRunning();
            }
        }
        /// <summary>
        /// 托管服务已运行
        /// </summary>
        public event WindowsServiceHostingEventHandler WindowsServiceHostingRunning;
        #endregion

        #region 停止中
        void OnWindowsServiceHostingStoping()
        {
            if (this.WindowsServiceHostingStoping != null)
            {
                this.WindowsServiceHostingStoping();
            }
        }
        /// <summary>
        /// 托管服务正在停止
        /// </summary>
        public event WindowsServiceHostingEventHandler WindowsServiceHostingStoping;
        #endregion

        #region 已停止
        /// <summary>
        /// 托管服务已停止
        /// </summary>
        public event WindowsServiceHostingEventHandler WindowsServiceHostingStopped;

        void OnWindowsServiceHostingStopped()
        {
            if (this.WindowsServiceHostingStopped != null)
            {
                this.WindowsServiceHostingStopped();
            }
        }

        #endregion

        #region 已连接
        void OnWindowsServiceHostingConnected()
        {
            if (this.WindowsServiceHostingConnected != null)
            {
                this.WindowsServiceHostingConnected();
            }
        }
        /// <summary>
        /// 托管服务已连接
        /// </summary>
        public event WindowsServiceHostingEventHandler WindowsServiceHostingConnected;
        #endregion

        #region 已断开
        void OnWindowsServiceHostingDisconnected()
        {
            if (this.WindowsServiceHostingDisconnected != null)
            {
                this.WindowsServiceHostingDisconnected();
            }
        }
        /// <summary>
        /// 托管服务已断开
        /// </summary>
        public event WindowsServiceHostingEventHandler WindowsServiceHostingDisconnected;
        #endregion

        #endregion

        #region WindowsServiceEventHandler

        /// <summary>
        /// 服务正在启动
        /// </summary>
        public event WindowsServiceEventHandler WindowsServiceStarting;

        void OnWindowsServiceStarting(string serviceId, string serviceName)
        {
            if (this.WindowsServiceStarting != null)
            {
                this.WindowsServiceStarting(serviceId, serviceName);
            }
        }


        /// <summary>
        /// 服务已运行
        /// </summary>
        public event WindowsServiceEventHandler WindowsServiceRunning;

        void OnWindowsServiceRunning(string serviceId, string serviceName)
        {
            if (this.WindowsServiceRunning != null)
            {
                this.WindowsServiceRunning(serviceId, serviceName);
            }
        }


        /// <summary>
        /// 服务正在停止
        /// </summary>
        public event WindowsServiceEventHandler WindowsServiceStoping;
        void OnWindowsServiceStoping(string serviceId, string serviceName)
        {
            if (this.WindowsServiceStoping != null)
            {
                this.WindowsServiceStoping(serviceId, serviceName);
            }
        }


        /// <summary>
        /// 服务已停止
        /// </summary>
        public event WindowsServiceEventHandler WindowsServiceStopped;
        void OnWindowsServiceStopped(string serviceId, string serviceName)
        {
            if (this.WindowsServiceStopped != null)
            {
                this.WindowsServiceStopped(serviceId, serviceName);
            }
        }


        #endregion

        #region IpcChannel

        /// <summary>
        /// 初始化托管服务控制器客户端
        /// </summary>
        /// <param name="controller">控制器实例</param>
        /// <returns></returns>
        static WindowsServiceHosting GetRemotingWindowServiceHosting()
        {
            Channels.RegisterIpcChannel(Constants.HostingClientChannelName);

            return (WindowsServiceHosting)Activator.GetObject(typeof(WindowsServiceHosting), string.Format("ipc://{0}/{1}", Constants.HostingServiceChannelName, Constants.HostingObjectUri));

        }
        #endregion

        public IEnumerable<IBundleContext> GetBundles()
        {
            return this._WindowsServiceHosting.BundleContextes;
        }
    }



    /// <summary>
    /// <see cref="WindowsServiceHosting"/>状态事件委托
    /// </summary>
    public delegate void WindowsServiceHostingEventHandler();

    /// <summary>
    /// <see cref="IWindowsService"/>状态事件委托
    /// </summary>
    /// <param name="serviceId"></param>
    /// <param name="serviceName"></param>
    public delegate void WindowsServiceEventHandler(string serviceId, string serviceName);

}
